﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Properties;
using NHibernate.Linq;
using NHibernate.Criterion;

namespace DataAccessObject.Hibernate
{
    /// <summary>
    /// 抽象类，提供基本的数据库操作集
    /// 不能实例化
    /// </summary>
    public class NhDao : IDao
    {
        /// <summary>
        /// 供外界使用的Hibernate会话
        /// </summary>
        public ISession session { get; set; }
      
        #region 基本操作
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T Get<T>(object id)
        {
            return session.Get<T>(id);
        }

        /// <summary>
        /// POID
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T Load<T>(object id)
        {
            return session.Load<T>(id);
        }

        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual bool Exist<T>(object id)
        {
            if (session.Get<T>(id) != null)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual int Exist<T>(ICriterion expression) where T : class
        {
            ICriteria query = session.CreateCriteria<T>();
            //设置条件
            if (expression != null)
            {
                query.Add(expression);
            }
            //获取记录总数
            int total = Convert.ToInt32(query.SetProjection(Projections.RowCount()).UniqueResult());
            return total;
        }
        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual object Save(object obj)
        {
            return session.Save(obj);
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="obj"></param>
        public virtual void Update(object obj)
        {
            session.Update(obj);
        }

        /// <summary>
        /// 保存或更新
        /// </summary>
        /// <param name="obj"></param>
        public virtual void SaveOrUpdate(object obj)
        {
            session.SaveOrUpdate(obj);
        }
        /// <summary>
        /// 合并
        /// </summary>
        /// <param name="id"></param>
        public virtual object Merge(object obj) {
            return session.Merge(obj);
        }
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        public virtual void Delete(object obj)
        {
            session.Delete(obj);
        }

        /// <summary>
        /// 按ID删除
        /// </summary>
        /// <param name="id"></param>
        public virtual void Delete<T>(object id)
        {
            T obj = this.Get<T>(id);
            if (obj != null)
            {
                session.Delete(obj);
            }
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="ids"></param>
        public virtual void Delete<T>(IEnumerable<object> ids)
        {
            foreach (object id in ids)
            {
                T obj = this.Get<T>(id);
                if (obj != null)
                {
                    session.Delete(obj);
                }
            }
            session.Flush();
        }

        /// <summary>
        /// 按HQL查询语句删除
        /// </summary>
        /// <param name="id"></param>
        public virtual void Delete(string query)
        {
            session.Delete(query);
        }
        #endregion

        #region 条件查询
        /// <summary>
        /// Linq 查询
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual IList<T> FindBy<T>(Func<T, bool> expression)
        {
            IList<T> list = session.Query<T>().Where(expression).ToList();
            return list;
        }

        /// <summary>
        /// Criterion 查询
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual IList<T> FindBy<T>(ICriterion expression, Order order = null) where T : class
        {
            ICriteria query = session.CreateCriteria<T>();
            query.SetReadOnly(true);
            if (expression != null)
            {
                query.Add(expression);
            }
            if (order != null)
            {
                query.AddOrder(order);
            }
            return query.List<T>();
        }

        /// <summary>
        /// Criterion 查询
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual IList<T> FindBy<T>(IEnumerable<ICriterion> expression, Order order = null) where T : class
        {
            ICriteria query = session.CreateCriteria<T>();
            query.SetReadOnly(true);
            if (expression != null)
            {
                foreach (ICriterion exp in expression)
                {
                    query.Add(exp);
                }
            }
            if (order != null)
            {
                query.AddOrder(order);
            }
            return query.List<T>();
        }

        public virtual IList<T> FindBy<T>(IEnumerable<ICriterion> expression, IEnumerable<Order> orders) where T : class
        {
            ICriteria query = session.CreateCriteria<T>();
            query.SetReadOnly(true);
            if (expression != null)
            {
                foreach (ICriterion exp in expression)
                {
                    query.Add(exp);
                }
            }
            //设置排序
            if (orders != null)
            {
                foreach (Order o in orders)
                {
                    query.AddOrder(o);
                }
            }
            return query.List<T>();
        }

        /// <summary>
        /// 查询全部
        /// </summary>
        /// <returns></returns>
        public virtual IList<T> FindAll<T>(Order order = null) where T : class
        {
            ICriteria query = session.CreateCriteria<T>();
            query.SetReadOnly(true);
            if (order != null)
            {
                query.AddOrder(order);
            }
            return query.List<T>();
        }

        /// <summary>
        /// 查询前top条记录
        /// </summary>
        /// <param name="top"></param>
        /// <param name="expression"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public virtual IList<T> Top<T>(int top, ICriterion expression = null, Order order = null) where T : class
        {
            ICriteria query = session.CreateCriteria<T>();
            query.SetReadOnly(true);
            if (expression != null)
            {
                query.Add(expression);
            }
            if (order != null)
            {
                query.AddOrder(order);
            }
            query.SetMaxResults(top);
            return query.List<T>();
        }
        #endregion

        #region 统计
        /// <summary>
        /// 统计总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public virtual int Count<T>() where T : class
        {
            ICriteria criteria = session.CreateCriteria<T>();
            return Convert.ToInt32(criteria.SetProjection(Projections.RowCount()).UniqueResult());
        }
        /// <summary>
        /// 统计总数 带 表达式
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual int Count<T>(ICriterion expression) where T : class
        {
            ICriteria criteria = session.CreateCriteria<T>();
            if (expression != null)
            {
                criteria.Add(expression);
            }
            return Convert.ToInt32(criteria.SetProjection(Projections.RowCount()).UniqueResult());
        }
        /// <summary>
        /// 统计总数 带 表达式
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual int Count<T>(IList<ICriterion> expressions) where T : class
        {
            ICriteria criteria = session.CreateCriteria<T>();
            if (expressions != null)
            {
                foreach (ICriterion exp in expressions)
                {
                    criteria.Add(exp);
                }
            }
            return Convert.ToInt32(criteria.SetProjection(Projections.RowCount()).UniqueResult());
        }
        /// <summary>
        /// 统计总数 带 表达式
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual decimal Sum<T>(string property, ICriterion expression = null) where T : class
        {
            ICriteria criteria = session.CreateCriteria<T>();
            if (expression != null)
            {
                criteria.Add(expression);
            }
            decimal num = Convert.ToDecimal(criteria.SetProjection(Projections.Sum(property)).UniqueResult());
            return decimal.Round(num, 2);
        }

        /// <summary>
        /// 统计总数 带 表达式
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual long SumLong<T>(string property, ICriterion expression = null) where T : class
        {
            ICriteria criteria = session.CreateCriteria<T>();
            if (expression != null)
            {
                criteria.Add(expression);
            }
            return Convert.ToInt64(criteria.SetProjection(Projections.Sum(property)).UniqueResult());
        }
        #endregion

        #region 分页查询
        public virtual Pagination<T> Query<T>(int pageIndex, int pageSize, IEnumerable<ICriterion> expressions = null, IEnumerable<Order> orders = null) where T : class
        {
            ICriteria query = session.CreateCriteria<T>();
            query.SetReadOnly(true);
            //条件
            if (expressions != null)
            {
                foreach (ICriterion o in expressions)
                {
                    query.Add(o);
                }
            }

            Pagination<T> pager = new Pagination<T>();
            pager.pageSize = pageSize;
            pager.pageIndex = pageIndex;
            pager.total = Convert.ToInt32(query.SetProjection(Projections.RowCount()).UniqueResult());//获取记录总数

            //ICriteria queryPage = CriteriaTransformer.Clone(query);
            //排序
            if (orders != null)
            {
                foreach (Order o in orders)
                {
                    query.AddOrder(o);
                }
            }

            query.SetFirstResult(pager.start);
            query.SetMaxResults(pager.pageSize);
            pager.items = query.List<T>();
            return pager;
        }

        #endregion

        public int Execute(string hql)
        {
            return session.CreateSQLQuery(hql).ExecuteUpdate();
        }
    }
}
